{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# HopperBulletEnv with Twin Delayed DDPG (TD3)\n",
    "\n",
    "### Paper: https://arxiv.org/abs/1802.09477\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Start the Environment and Agent "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "current_dir=/home/rafaels/ml-agents/lib/python3.7/site-packages/pybullet_envs/bullet\n",
      "device:  cpu\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import pybullet_envs\n",
    "import pybullet_envs.bullet as bul\n",
    "\n",
    "#from torch.autograd import Variable\n",
    "import torch.nn.functional as F\n",
    "\n",
    "import gym\n",
    "#import argparse\n",
    "import os\n",
    "\n",
    "import time\n",
    "from TwinDelayed import Actor, Critic, ReplayBuffer, TD3\n",
    "from collections import deque\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "start_dim:  26 , action_dim:  6\n",
      "n max_action:  1.0 , threshold:  3000.0\n"
     ]
    }
   ],
   "source": [
    "start_timestep=1e4\n",
    "\n",
    "std_noise=0.05\n",
    "\n",
    "env = gym.make('HalfCheetahBulletEnv-v0')\n",
    "\n",
    "# Set seeds\n",
    "seed = 12345\n",
    "env.seed(seed)\n",
    "torch.manual_seed(seed)\n",
    "np.random.seed(seed)\n",
    "\n",
    "state = env.reset()\n",
    "state_dim = env.observation_space.shape[0]\n",
    "action_dim = env.action_space.shape[0] \n",
    "max_action = float(env.action_space.high[0])\n",
    "threshold = env.spec.reward_threshold\n",
    "\n",
    "print('start_dim: ', state_dim, ', action_dim: ', action_dim)\n",
    "print('n max_action: ', max_action, ', threshold: ', threshold)\n",
    "\n",
    "agent = TD3(state_dim, action_dim, max_action)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Traning the agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# save(agent = agent, filename='checkpnt, directory = 'dir_chkpoint')     \n",
    "def save(agent, filename, directory):\n",
    "    torch.save(agent.actor.state_dict(), '%s/%s_actor.pth' % (directory, filename))\n",
    "    torch.save(agent.critic.state_dict(), '%s/%s_critic.pth' % (directory, filename))\n",
    "    torch.save(agent.actor_target.state_dict(), '%s/%s_actor_t.pth' % (directory, filename))\n",
    "    torch.save(agent.critic_target.state_dict(), '%s/%s_critic_t.pth' % (directory, filename))   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Low in action space:  [-1. -1. -1. -1. -1. -1.] , High:  [1. 1. 1. 1. 1. 1.] , Action_dim:  6\n",
      "Ep. 40, Timestep 40000,  Ep.Timesteps 1000, Score: 562.43, Avg.Score: -530.70, Max.Score: 730.57,  Time: 00:15:45 \n",
      "Ep. 80, Timestep 80000,  Ep.Timesteps 1000, Score: -1357.29, Avg.Score: -392.62, Max.Score: 828.02,  Time: 00:34:02 \n",
      "Ep. 120, Timestep 120000,  Ep.Timesteps 1000, Score: 786.83, Avg.Score: -51.67, Max.Score: 864.29,  Time: 00:58:47 \n",
      "Ep. 160, Timestep 160000,  Ep.Timesteps 1000, Score: 524.97, Avg.Score: 116.19, Max.Score: 981.76,  Time: 01:25:48 \n",
      "Ep. 200, Timestep 200000,  Ep.Timesteps 1000, Score: 859.46, Avg.Score: 738.09, Max.Score: 1105.64,  Time: 01:54:04 \n",
      "Ep. 240, Timestep 240000,  Ep.Timesteps 1000, Score: 1706.64, Avg.Score: 925.84, Max.Score: 1706.64,  Time: 02:22:41 \n",
      "Ep. 280, Timestep 280000,  Ep.Timesteps 1000, Score: 1754.34, Avg.Score: 1321.94, Max.Score: 1872.41,  Time: 02:51:40 \n",
      "Ep. 320, Timestep 320000,  Ep.Timesteps 1000, Score: 1774.92, Avg.Score: 1642.55, Max.Score: 1918.99,  Time: 03:21:06 \n",
      "Ep. 360, Timestep 360000,  Ep.Timesteps 1000, Score: 1946.79, Avg.Score: 1773.85, Max.Score: 2006.74,  Time: 03:50:46 \n",
      "Ep. 400, Timestep 400000,  Ep.Timesteps 1000, Score: 2016.79, Avg.Score: 1876.10, Max.Score: 2112.32,  Time: 04:20:33 \n",
      "Ep. 440, Timestep 440000,  Ep.Timesteps 1000, Score: 2085.11, Avg.Score: 2011.62, Max.Score: 2181.58,  Time: 04:50:35 \n",
      "Ep. 480, Timestep 480000,  Ep.Timesteps 1000, Score: 1978.83, Avg.Score: 2084.02, Max.Score: 2232.53,  Time: 05:20:42 \n",
      "Ep. 520, Timestep 520000,  Ep.Timesteps 1000, Score: 2239.65, Avg.Score: 2158.41, Max.Score: 2314.94,  Time: 05:50:55 \n",
      "Ep. 560, Timestep 560000,  Ep.Timesteps 1000, Score: 2236.01, Avg.Score: 2236.15, Max.Score: 2393.00,  Time: 06:21:15 \n",
      "Ep. 600, Timestep 600000,  Ep.Timesteps 1000, Score: 2336.87, Avg.Score: 2295.60, Max.Score: 2393.00,  Time: 06:51:41 \n",
      "Ep. 640, Timestep 640000,  Ep.Timesteps 1000, Score: 2364.52, Avg.Score: 2334.35, Max.Score: 2445.17,  Time: 07:22:07 \n",
      "Ep. 680, Timestep 680000,  Ep.Timesteps 1000, Score: 2384.01, Avg.Score: 2364.28, Max.Score: 2489.68,  Time: 07:52:46 \n",
      "Ep. 720, Timestep 720000,  Ep.Timesteps 1000, Score: 2514.02, Avg.Score: 2401.34, Max.Score: 2525.51,  Time: 08:23:36 \n",
      "Ep. 760, Timestep 760000,  Ep.Timesteps 1000, Score: 2487.85, Avg.Score: 2469.99, Max.Score: 2585.60,  Time: 08:54:40 \n",
      "Ep. 800, Timestep 800000,  Ep.Timesteps 1000, Score: 2639.11, Avg.Score: 2526.32, Max.Score: 2650.28,  Time: 09:25:45 \n",
      "Ep. 840, Timestep 840000,  Ep.Timesteps 1000, Score: 2651.67, Avg.Score: 2582.90, Max.Score: 2713.32,  Time: 09:57:04 \n",
      "Ep. 880, Timestep 880000,  Ep.Timesteps 1000, Score: 2716.79, Avg.Score: 2632.66, Max.Score: 2733.48,  Time: 10:28:28 \n",
      "Ep. 920, Timestep 920000,  Ep.Timesteps 1000, Score: 2705.72, Avg.Score: 2661.62, Max.Score: 2733.48,  Time: 10:59:59 \n",
      "Ep. 960, Timestep 960000,  Ep.Timesteps 1000, Score: 2630.16, Avg.Score: 2684.93, Max.Score: 2769.85,  Time: 11:31:31 \n",
      "Ep. 1000, Timestep 1000000,  Ep.Timesteps 1000, Score: 2776.03, Avg.Score: 2709.53, Max.Score: 2821.04,  Time: 12:03:07 \n",
      "Ep. 1040, Timestep 1040000,  Ep.Timesteps 1000, Score: 2782.59, Avg.Score: 2735.53, Max.Score: 2821.04,  Time: 12:35:17 \n",
      "Ep. 1080, Timestep 1080000,  Ep.Timesteps 1000, Score: 2771.93, Avg.Score: 2762.16, Max.Score: 2876.49,  Time: 13:08:09 \n",
      "Ep. 1120, Timestep 1120000,  Ep.Timesteps 1000, Score: 2828.29, Avg.Score: 2782.87, Max.Score: 2882.22,  Time: 13:42:13 \n",
      "Ep. 1160, Timestep 1160000,  Ep.Timesteps 1000, Score: 2840.41, Avg.Score: 2809.52, Max.Score: 2891.87,  Time: 14:17:21 \n",
      "Ep. 1200, Timestep 1200000,  Ep.Timesteps 1000, Score: 2829.58, Avg.Score: 2828.05, Max.Score: 2903.42,  Time: 14:54:00 \n",
      "Ep. 1240, Timestep 1240000,  Ep.Timesteps 1000, Score: 2840.40, Avg.Score: 2836.02, Max.Score: 2928.44,  Time: 15:31:37 \n",
      "Ep. 1280, Timestep 1280000,  Ep.Timesteps 1000, Score: 2814.58, Avg.Score: 2845.35, Max.Score: 2928.44,  Time: 16:10:07 \n",
      "Ep. 1320, Timestep 1320000,  Ep.Timesteps 1000, Score: 2498.79, Avg.Score: 2853.34, Max.Score: 2937.09,  Time: 16:49:19 \n",
      "Ep. 1360, Timestep 1360000,  Ep.Timesteps 1000, Score: 2939.48, Avg.Score: 2850.18, Max.Score: 2968.91,  Time: 17:28:23 \n",
      "Ep. 1400, Timestep 1400000,  Ep.Timesteps 1000, Score: 2904.48, Avg.Score: 2871.93, Max.Score: 2968.92,  Time: 18:07:41 \n",
      "Ep. 1440, Timestep 1440000,  Ep.Timesteps 1000, Score: 2906.16, Avg.Score: 2921.34, Max.Score: 2990.04,  Time: 18:47:28 \n",
      "Ep. 1480, Timestep 1480000,  Ep.Timesteps 1000, Score: 2990.21, Avg.Score: 2930.83, Max.Score: 3006.72,  Time: 19:27:47 \n",
      "Ep. 1520, Timestep 1520000,  Ep.Timesteps 1000, Score: 2956.65, Avg.Score: 2943.54, Max.Score: 3056.11,  Time: 20:08:34 \n",
      "Ep. 1560, Timestep 1560000,  Ep.Timesteps 1000, Score: 2906.25, Avg.Score: 2968.58, Max.Score: 3065.34,  Time: 20:49:32 \n",
      "Ep. 1588, Timestep 1588000,  Ep.Timesteps 1000, Score: 3031.24, Avg.Score: 3000.42, Max.Score: 3092.66,  Time: 21:18:20 \n",
      "Environment solved with Average Score:  3000.422371605943\n"
     ]
    }
   ],
   "source": [
    "# Twin Delayed Deep Deterministic (TD3) policy gradient algorithm\n",
    "def twin_ddd_train(n_episodes=15000, save_every=10, print_env=40):\n",
    "\n",
    "    scores_deque = deque(maxlen=100)\n",
    "    scores_array = []\n",
    "    avg_scores_array = []    \n",
    "\n",
    "    time_start = time.time()                    # Init start time\n",
    "    replay_buf = ReplayBuffer()                 # Init ReplayBuffer\n",
    "    \n",
    "    timestep_after_last_save = 0\n",
    "    total_timesteps = 0\n",
    "    \n",
    "    low = env.action_space.low\n",
    "    high = env.action_space.high\n",
    "    \n",
    "    print('Low in action space: ', low, ', High: ', high, ', Action_dim: ', action_dim)\n",
    "            \n",
    "    for i_episode in range(1, n_episodes+1):\n",
    "        \n",
    "        timestep = 0\n",
    "        total_reward = 0\n",
    "        \n",
    "        # Reset environment\n",
    "        state = env.reset()\n",
    "        done = False\n",
    "        \n",
    "        while True:\n",
    "            \n",
    "            # Select action randomly or according to policy\n",
    "            if total_timesteps < start_timestep:\n",
    "                action = env.action_space.sample()\n",
    "            else:\n",
    "                action = agent.select_action(np.array(state))\n",
    "                if std_noise != 0: \n",
    "                    shift_action = np.random.normal(0, std_noise, size=action_dim)\n",
    "                    action = (action + shift_action).clip(low, high)\n",
    "            \n",
    "            # Perform action\n",
    "            new_state, reward, done, _ = env.step(action) \n",
    "            done_bool = 0 if timestep + 1 == env._max_episode_steps else float(done)\n",
    "            total_reward += reward                          # full episode reward\n",
    "\n",
    "            # Store every timestep in replay buffer\n",
    "            replay_buf.add((state, new_state, action, reward, done_bool))\n",
    "            state = new_state\n",
    "\n",
    "            timestep += 1     \n",
    "            total_timesteps += 1\n",
    "            timestep_after_last_save += 1\n",
    "\n",
    "            if done:                                       # done ?\n",
    "                break                                      # save score\n",
    "\n",
    "        scores_deque.append(total_reward)\n",
    "        scores_array.append(total_reward)\n",
    "\n",
    "        avg_score = np.mean(scores_deque)\n",
    "        avg_scores_array.append(avg_score)\n",
    "        \n",
    "        max_score = np.max(scores_deque)\n",
    "        \n",
    "        # train_by_episode(time_start, i_episode) \n",
    "        s = (int)(time.time() - time_start)\n",
    "        if i_episode % print_env == 0 or (len(scores_deque) == 100 and avg_score > threshold):\n",
    "            print('Ep. {}, Timestep {},  Ep.Timesteps {}, Score: {:.2f}, Avg.Score: {:.2f}, Max.Score: {:.2f},  Time: {:02}:{:02}:{:02} '\\\n",
    "                .format(i_episode, total_timesteps, timestep, \\\n",
    "                        total_reward, avg_score, max_score, s//3600, s%3600//60, s%60))     \n",
    "\n",
    "        agent.train(replay_buf, timestep)\n",
    "\n",
    "        # Save episode if more than save_every=5000 timesteps\n",
    "        if timestep_after_last_save >= save_every and i_episode > 0:\n",
    "\n",
    "            timestep_after_last_save %= save_every            \n",
    "            save(agent, 'chpnt_1', 'dir_chk_005')  \n",
    "        \n",
    "        if len(scores_deque) == 100 and avg_score >= threshold:\n",
    "            print('Environment solved with Average Score: ',  avg_score )\n",
    "            break \n",
    "\n",
    "    return scores_array, avg_scores_array\n",
    "\n",
    "scores, avg_scores = twin_ddd_train()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "save(agent, 'chpnt_2', 'dir_chk_005')  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "length of scores:  1588 , len of avg_scores:  1588\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "print('length of scores: ', len(scores), ', len of avg_scores: ', len(avg_scores))\n",
    "\n",
    "fig = plt.figure()\n",
    "ax = fig.add_subplot(111)\n",
    "plt.plot(np.arange(1, len(scores)+1), scores, label=\"Score\")\n",
    "plt.plot(np.arange(1, len(avg_scores)+1), avg_scores, label=\"Avg on 100 episodes\")\n",
    "plt.legend(bbox_to_anchor=(1.05, 1)) \n",
    "plt.ylabel('Score')\n",
    "plt.xlabel('Episodes #')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Episode 1\tAverage Score: 3081.87,\tScore: 3081.87 \tTime: 00:00:13\n",
      "Episode 2\tAverage Score: 3079.75,\tScore: 3077.63 \tTime: 00:00:13\n",
      "Episode 3\tAverage Score: 3082.72,\tScore: 3088.66 \tTime: 00:00:13\n",
      "Episode 4\tAverage Score: 3083.66,\tScore: 3086.50 \tTime: 00:00:13\n",
      "Episode 5\tAverage Score: 3084.28,\tScore: 3086.72 \tTime: 00:00:13\n",
      "Episode 6\tAverage Score: 3086.68,\tScore: 3098.72 \tTime: 00:00:13\n",
      "Episode 7\tAverage Score: 3084.11,\tScore: 3068.66 \tTime: 00:00:13\n",
      "Episode 8\tAverage Score: 3082.48,\tScore: 3071.07 \tTime: 00:00:13\n",
      "Episode 9\tAverage Score: 3082.85,\tScore: 3085.86 \tTime: 00:00:13\n",
      "Episode 10\tAverage Score: 3083.18,\tScore: 3086.10 \tTime: 00:00:13\n"
     ]
    }
   ],
   "source": [
    "from collections import deque\n",
    "import os\n",
    "\n",
    "def play(env, agent, n_episodes):\n",
    "    state = env.reset()\n",
    "    \n",
    "    scores_deque = deque(maxlen=100)\n",
    "    scores = []\n",
    "\n",
    "    for i_episode in range(1, n_episodes+1):\n",
    "        state = env.reset()        \n",
    "        score = 0\n",
    "        \n",
    "        time_start = time.time()\n",
    "        \n",
    "        while True:\n",
    "            action = agent.select_action(np.array(state))\n",
    "            env.render()\n",
    "            time.sleep(0.01)\n",
    "            next_state, reward, done, _ = env.step(action)\n",
    "            state = next_state\n",
    "            score += reward\n",
    "            if done:\n",
    "                break \n",
    "\n",
    "        s = (int)(time.time() - time_start)\n",
    "        \n",
    "        scores_deque.append(score)\n",
    "        scores.append(score)\n",
    "        \n",
    "        print('Episode {}\\tAverage Score: {:.2f},\\tScore: {:.2f} \\tTime: {:02}:{:02}:{:02}'\\\n",
    "                  .format(i_episode, np.mean(scores_deque), score, s//3600, s%3600//60, s%60))  \n",
    "\n",
    "play(env=env, agent=agent, n_episodes=10)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "env.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
